/**

This file is part of MaCI/GIMnet.

MaCI/GIMnet is free software: you can redistribute it and/or modify it 
under the terms of the GNU Lesser General Public License as published 
by the Free Software Foundation, either version 3 of the License, or 
(at your option) any later version.

MaCI/GIMnet is distributed in the hope that it will be useful, but WITHOUT 
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public 
License for more details.

You should have received a copy of the GNU Lesser General Public 
License along with GIMnet. (See COPYING.LESSER) If not, see 
<http://www.gnu.org/licenses/>.

**/
#ifndef SIMPLEBUFFER_H_
#define SIMPLEBUFFER_H_

#include "gimiutils.h"

namespace gimi {

//TODO Method for freeing allocated but unused buffer.
/**
 * Simple dynamic buffer (does not reduce amount of allocated memory until destroyed.)
 */
class SimpleBuffer
{
  public:
    SimpleBuffer(const int initialSize,
                 const int maximumSize)
      : buffer (new char[initialSize]), currentSize (0),
        currentAllocatedSize (initialSize), maxAllocatedSize (maximumSize) {};
    ~SimpleBuffer();
    
    /**
     * Returns pointer to the start of buffer
     */
    inline const char* getBufferPtr() const { return buffer; };
    
    /**
     * Returns pointer to first free byte in buffer.
     */
    inline char* getFreeBufferPtr() const { return buffer+currentSize; }; 
    
    /**
     * Update buffer size in case pointer to free buffer was used directly.
     */
    inline void updateBufferSize(const int addedBytes) { currentSize += addedBytes; };
    
    /**
     * Returns current buffer size.
     */
    inline int getBufferLength() const { return currentSize; };
    
    /**
     * Returns amount of unallocated buffer left.
     */
    inline int getUnallocatedLength() const { return currentAllocatedSize - currentSize; };
    
    /**
     * Allocates additionSize bytes more to the buffer.
     * \note Invalidates pointers gotten from getBufferPtr and getFreeBufferPtr!
     * 
     * \return GIMI_OK or GIMI_ERROR if maximum size would be exceeded.
     */
    int allocateMoreBuffer(const int additionSize);
    
    /**
     * Inserts given data to buffer, allocates more space if needed.
     * \note May invalidate pointers gotten from getBufferPtr and getFreeBufferPtr! 
     * \return GIMI_OK, GIMI_ERROR
     */
    int pushData(const char* data,
                 const int dataLength);
    
    /**
     * Shift rest of the buffer from position nBytes to the beginning of the buffer.
     * Checks nBytes value sanity with assert.
     * 
     * \return GIMI_OK, GIMI_ERROR
     */
    int shiftBuffer(const int nBytes);
    
    /**
     * Empties buffer.
     */
    inline void clearBuffer() { currentSize = 0; };
    
  private:
    SimpleBuffer(const SimpleBuffer& right);
    const SimpleBuffer& operator=(const SimpleBuffer &right);
    
    char* buffer;
    int currentSize;
    int currentAllocatedSize;
    const int maxAllocatedSize; //TODO Not used right now.
};

}; // end namespace gimi

#endif /*SIMPLEBUFFER_H_*/
